package tld.test.interpreter
{
	public class Context implements IContext
	{
		private const _names:Object = { };
		
		private var _parent:IContext;
		
		public function Context(parent:IContext)
		{
			super();
			this._parent = parent;
		}
		
		public static function merge(a:Object, b:Object):Object
		{
			var result:Object = { };
			var name:String;
			for (name in a)
				result[name] = a[name];
			for (name in b)
				if (!(name in result)) result[name] = b[name];
			return result;
		}

		public function getParent():IContext
		{
			return this._parent;
		}
		
		public function getNames():Object
		{
			var result:Object;
			
			if (this._parent)
				result = merge(this, this._parent);
			else result = this._names;
			return result;
		}
		
		public function put(name:String, value:Object = null):void
		{
			this.getNames()[name] = value;
		}
		
		public function setParent(parent:IContext):IContext
		{
			return this._parent = parent;
		}
		
		public function resolve(name:String):Object
		{
			var current:IContext = this;
			var result:Object;
			var maybeNumber:Number = parseFloat(name);
			
			if (!isNaN(maybeNumber)) result = maybeNumber;
			else
			{
				while (current)
				{
					if (name in current.getNames())
					{
						result = current.resolve(name);
						break;
					}
					else current = current.getParent();
				}
			}
			return result; 
		}
	}
}